#pragma once

#include "tcp_syn_packet_process.h"
#include <string>

struct proxy_info
{
	proxy_info()
	{
		reset();
	}
	void reset()
	{
		is_set = false;
		ip = "";
		user = "";
		pwd = "";
		port = 0;
		type = 0;
	}
	std::string ip;
	int port;
	std::string user;
	std::string pwd;
	bool is_set;
	int type;
};

class tcp_syn_event_handler : public ACE_Event_Handler
{
public:
	tcp_syn_event_handler(ACE_Reactor *reactor);
	virtual ~tcp_syn_event_handler(void);
public:
	virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, ACE_Reactor_Mask = 0);
	virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE);
	virtual int handle_output (ACE_HANDLE = ACE_INVALID_HANDLE);
	virtual int handle_timeout (const ACE_Time_Value &current_time, const void *act = 0);
	virtual ACE_HANDLE get_handle () const;
public:
	void set_dummy_http_tunnel_host(const char* host_name, int host_port)
	{
		this->dummy_ht_host_name_ = host_name;
		this->dummy_ht_host_port_ = host_port;
	}
	void set_proxy(const char* ip, int port, const char* user, const char* pwd, int type)
	{
		this->proxy_info_.ip = ip;
		this->proxy_info_.port = port;
		this->proxy_info_.user = user;
		this->proxy_info_.pwd = pwd;
		this->proxy_info_.is_set = true;
		this->proxy_info_.type = type;
	}
	void clr_proxy()
	{
		this->proxy_info_.reset();
	}
	int connect(ACE_INET_Addr& addr, int serv_type, const aot::inet::inet_time_t* tm_out = NULL);
	void set_heartbeat_time(const aot::inet::inet_time_t* tm, const aot::inet::inet_time_t* max_tm_out);
	int put_to_send_queue(aot::inet::ipacket* pkt, const aot::inet::inet_time_t* tm_out = NULL);
	int get_from_recv_queue(aot::inet::ipacket** pkt, const aot::inet::inet_time_t* tm_out = NULL);
	void close();

	aot::inet::inet_addr_t* local_addr();
	aot::inet::inet_addr_t* remote_addr();

	void set_send_buf_size(size_t size);
	void set_recv_buf_size(size_t size);
	bool http_proxy_shake_hand(ACE_INET_Addr& addr, int* ret_code);
	static bool test_proxy(ACE_INET_Addr& proxy_addr, const char* proxy_auth, ACE_INET_Addr& forward_addr, const aot::inet::inet_time_t* tm_out, int* ret_code);
private:
	static bool __http_tunnel_shake_hand(ACE_SOCK_Stream& sock, const char* proxy_auth, const char* forward_host_name, int forward_host_port, int* ret_code);
public:
	ACE_SOCK_Stream	so_peer_;
	DWORD last_send_tm_;
	DWORD last_recv_tm_;
	DWORD heartbeat_tm_;
	DWORD max_heartbeat_tmout_;
	long heart_beat_tm_id_;

	tcp_syn_packet_sender pkt_sender_;
	tcp_syn_packet_recver pkt_recver_;

	aot::inet::inet_addr_t remote_addr_;
	aot::inet::inet_addr_t local_addr_;
	proxy_info proxy_info_;
	int serv_type_;
	std::string dummy_ht_host_name_;
	int dummy_ht_host_port_;
};
